/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package generadorcommun;

import com.mysql.jdbc.ResultSet;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 *
 * @author Martin
 */
public class CrearPersistencia {

    private static CrearPersistencia instance;

    private CrearPersistencia() {
    }

    public static CrearPersistencia getInstance() {
        if (instance == null) {
            instance = new CrearPersistencia();
        }
        return instance;
    }

    public void crearFirma(List<String> claseP, String nombreClase, String paquete) throws IOException {
        claseP.add("package " + paquete + ";");
        claseP.add("import java.sql.*;");
        claseP.add("public class Persistencia" + nombreClase + "{");
        claseP.add("}");
        generarSingleton(claseP, nombreClase);
    }

    public String darNom(String nom) {
        String nombreA = "";
        nombreA += nom.charAt(0);
        nombreA.toUpperCase();
        for (int i = 1; i < nom.length(); i++) {
            nombreA += nom.charAt(i);
        }
        return nombreA;
    }

    public boolean esTipoBasico(String tipo) {
        boolean res = false;
        String aux = tipo.toUpperCase();
        if (aux.equals("INTEGER")) {
            res = true;
        } else if (aux.equals("DOUBLE")) {
            res = true;
        } else if (aux.equals("CHAR")) {
            res = true;
        } else if (aux.equals("BOOLEAN")) {
            res = true;
        } else if (aux.equals("LONG")) {
            res = true;
        } else if (aux.equals("FLOAT")) {
            res = true;
        }
        return res;
    }

    public File darDirSingleton(int i) {
        File dir = null;
        switch (i) {
            case 1:
                dir = new File("TXTGENERADOR/singleton_1.txt");
                break;
            case 2:
                dir = new File("TXTGENERADOR/singleton_2.txt");
                break;
            case 3:
                dir = new File("TXTGENERADOR/singleton_3.txt");
                break;
            case 4:
                dir = new File("TXTGENERADOR/singleton_4.txt");
                break;
            case 5:
                dir = new File("TXTGENERADOR/singleton_5.txt");
                break;
            case 6:
                dir = new File("TXTGENERADOR/singleton_6.txt");
                break;
        }
        return dir;
    }

    public void concatenarList(List<String> principal, List<String> secundario) {
        for (String linea : secundario) {
            principal.add(principal.size() - 1, linea);
        }
    }

    public String sustituir(String texto, String sustituir) {
        String aux = "";
        for (char c : texto.toCharArray()) {
            if (c == '%') {
                aux = aux + sustituir;
            } else {
                aux = aux + c;
            }
        }
        return aux;
    }

    public void generarSingleton(List<String> clase, String nombre) throws IOException {
        for (int i = 1; i <= 6; i++) {
            if (i == 4 || i == 6) {
                concatenarList(clase, GuardarArchivo.getInstance().leerTxt(darDirSingleton(i)));
            } else {
                clase.add(clase.size() - 1, sustituir(GuardarArchivo.getInstance().leerTxt(darDirSingleton(i)).get(0), "Persistencia" + nombre));
            }
        }
    }

    public void generarInsert(List<String> claseP, String Parametros, String campos, String valores, String tabla, String nombMetodo) {
        claseP.add(claseP.size() - 1, "public void insert" + nombMetodo + "(" + Parametros + ") throws SQLException{");
        String sentencia = "";
        String sentencia1 = "String sentencia=" + '"' + "insert into " + tabla + " (";
        String sentencia2 = ") values (";
        String sentencia3 = ")" + '"' + ";";
        sentencia = sentencia1 + campos + sentencia2 + valores + sentencia3;
        claseP.add(claseP.size() - 1, sentencia);
        claseP.add(claseP.size() - 1, "DataBase.getInstance().ejecutarSentencia(sentencia);");
        claseP.add(claseP.size() - 1, "}");
    }

    public void crearInsert(List<Atributo> atributosNoBasicos, List<Atributo> listas, List<Atributo> atributos, List<String> claseP, String nombreClase, String nombreProyecto) throws IOException {
        try {
            List<Atributo> persistenciasModificar = new LinkedList<Atributo>();
            String campos = "";
            String valores = "";
            String nom = "";
            String coma = '"' + "," + '"';
            String apostrofe = '"' + "'" + '"';
            char c;
            boolean primero = true;
            for (Atributo a : atributos) {
                if (!a.getNombre().equals("id")) {
                    if (primero) {
                        primero = false;
                        nom = darNom(a.getNombre());
                        campos += a.getNombre();
                        if (a.getTipo().equals("String")) {
                            valores += '"' + "+" + apostrofe + "+" + nombreClase.toLowerCase() + ".get" + nom + "()" + "+" + apostrofe + "+" + '"';
                        } else {
                            valores += '"' + "+" + nombreClase.toLowerCase() + ".get" + nom + "()" + "+" + '"';
                        }
                    } else {
                        nom = darNom(a.getNombre());
                        campos += "," + a.getNombre();
                        if (a.getTipo().equals("String")) {
                            valores += "," + '"' + "+" + apostrofe + "+" + nombreClase.toLowerCase() + ".get" + nom + "()" + "+" + apostrofe + "+" + '"';
                        } else {
                            valores += '"' + "+" + coma + "+" + nombreClase.toLowerCase() + ".get" + nom + "()" + "+" + '"';
                        }
                    }
                }
            }
            for (Atributo aNB : atributosNoBasicos) {
                campos += ",ID_FK" + aNB.getNombre();
                valores += '"' + "+" + '"' + "," + '"' + "+" + nombreClase.toLowerCase() + ".get" + aNB.getNombre().toLowerCase() + "().getid()+" + '"';
            }
            generarInsert(claseP, nombreClase + " " + nombreClase.toLowerCase(), campos, valores, nombreClase, "");
            String parametros = "";
            for (Atributo a : listas) {
                if (esTipoBasico(a.getTipo())) {
                    parametros = a.getTipo() + " dato , int id";
                    campos = a.getNombre() + ",ID_FK" + a.getNombre();
                    valores = '"' + "+dato+ " + '"' + " , " + '"' + "+id+" + '"';
                    generarInsert(claseP, parametros, campos, valores, a.getNombre(), "lista" + a.getNombre());
                } else if (a.getTipo().toUpperCase().equals("STRING")) {
                    parametros = a.getTipo() + " dato , int id";
                    campos = a.getNombre() + ",ID_FK" + a.getNombre();
                    valores = "'" + '"' + "+dato+" + '"' + "'" + "," + '"' + " +id+" + '"';
                    generarInsert(claseP, parametros, campos, valores, a.getNombre(), "lista" + a.getNombre());
                } else {
                    parametros = a.getTipo() + " " + a.getTipo().toLowerCase() + ",int id";
                    claseP.add(claseP.size() - 1, "public void insert" + a.getNombre() + "(" + parametros + ") throws SQLException {");
                    claseP.add(claseP.size() - 1, "Persistencia" + a.getTipo() + ".getInstance().insertFK(" + a.getTipo().toLowerCase() + ".getid()" + ", id," + '"' + "ID_FK" + a.getNombre() + '"' + ");");
                    claseP.add(claseP.size() - 1, "}");
                    claseP.add(claseP.size() - 1, "public void delete" + a.getNombre() + "(" + parametros + ") throws SQLException {");
                    claseP.add(claseP.size() - 1, "Persistencia" + a.getTipo() + ".getInstance().deleteFK(" + a.getTipo().toLowerCase() + ".getid()" + "," + '"' + "ID_FK" + a.getNombre() + '"' + ");");
                    claseP.add(claseP.size() - 1, "}");
                    persistenciasModificar.add(a);
                }
            }
            boolean repetido = false;
            File file = new File("FIRMASINSERT.txt");
            List<String> firmas = GuardarArchivo.getInstance().leerTxt(file);
            for (Atributo aModif : persistenciasModificar) {
                for (String txt : firmas) {
                    if (txt.equals(aModif.getTipo())) {
                        repetido = true;
                    }
                }
                if (!repetido) {
                    firmas.add(aModif.getTipo());
                    GuardarArchivo.getInstance().guardarFirmas(firmas, file);
                    modificarInsert(nombreProyecto, aModif.getTipo());
                }
            }
        } catch (Exception e) {
        }
    }

    public void modificarInsert(String nombreProy, String nombreClase) throws IOException {
        List<String> persistencia = buscarClasePersistencia(nombreProy, nombreClase);
        String metodoInset = "public void insertFK (int id ,int fk , String nombreFK)throws SQLException{";
        String metodoInset2 = "String sentencia = " + '"' + "update " + nombreClase + " set " + '"' + "+nombreFK +" + '"' + "= " + '"' + "+fk +" + '"' + "where ID = " + '"' + "+id" + ";";
        persistencia.add(persistencia.size() - 1, metodoInset);
        persistencia.add(persistencia.size() - 1, metodoInset2);
        persistencia.add(persistencia.size() - 1, "DataBase.getInstance().ejecutarSentencia(sentencia);");
        persistencia.add(persistencia.size() - 1, "}");

        String metodoDelete = "public void deleteFK (int id , String nombreFK)throws SQLException{";
        String metodoDelete2 = "String sentencia = " + '"' + "update " + nombreClase + " set " + '"' + "+nombreFK +" + '"' + "= null where ID = " + '"' + "+id" + ";";
        persistencia.add(persistencia.size() - 1, metodoDelete);
        persistencia.add(persistencia.size() - 1, metodoDelete2);
        persistencia.add(persistencia.size() - 1, "DataBase.getInstance().ejecutarSentencia(sentencia);");
        persistencia.add(persistencia.size() - 1, "}");

        GuardarArchivo.getInstance().persistirClase(persistencia, "Persistencia" + nombreClase, nombreProy, "class");
    }

    public List<String> buscarClasePersistencia(String nombreProy, String nombreClase) throws IOException {
        File dir = new File("C:/" + nombreProy + "/src/" + nombreProy + "/Persistencia" + nombreClase + ".java");
        return GuardarArchivo.getInstance().leerTxt(dir);
    }

    public void crearUpdate(List<String> claseP, List<Atributo> atributos, List<Atributo> atributosNoBasicos, List<Atributo> listas, String nombreClase) {
        String parametros = nombreClase + " " + nombreClase.toLowerCase();
        claseP.add(claseP.size() - 1, "public void update" + "(" + parametros + ")throws SQLException{");
        String apostrofe = '"' + "'" + '"';
        String sentencia = "String sentencia = " + '"' + "update " + nombreClase + " set ";
        boolean primero = true;
        for (Atributo a : atributos) {
            if (primero) {
                if (a.getTipo().equals("String")) {
                    sentencia += a.getNombre() + " = " + '"' + "+" + apostrofe + "+" + nombreClase.toLowerCase() + ".get" + a.getNombre() + "()+" + apostrofe + "+" + '"';
                } else {
                    sentencia += a.getNombre() + " = " + '"' + "+" + nombreClase.toLowerCase() + ".get" + a.getNombre() + "()" + "+" + '"';
                }
                primero = false;
            } else {
                if (a.getTipo().equals("String")) {
                    sentencia += "," + a.getNombre() + " = " + '"' + "+" + apostrofe + "+" + nombreClase.toLowerCase() + ".get" + a.getNombre() + "()+" + apostrofe + "+" + '"';
                } else {
                    sentencia += "," + a.getNombre() + " = " + '"' + "+" + nombreClase.toLowerCase() + ".get" + a.getNombre() + "()" + "+" + '"';
                }
            }
        }
        for (Atributo aNB : atributosNoBasicos) {
            if (primero) {
                primero = false;
                sentencia += " ID_FK" + aNB.getNombre() + " = " + '"' + "+" + nombreClase.toLowerCase() + ".get" + aNB.getNombre() + "().getid()" + "+" + '"';
            } else {
                sentencia += ", ID_FK" + aNB.getNombre() + " = " + '"' + "+" + nombreClase.toLowerCase() + ".get" + aNB.getNombre() + "().getid()" + "+" + '"';
            }
        }
        sentencia += " where id = " + '"' + "+" + nombreClase.toLowerCase() + '.' + "getid" + "()" + ";";
        claseP.add(claseP.size() - 1, sentencia);
        claseP.add(claseP.size() - 1, "DataBase.getInstance().ejecutarSentencia(sentencia);");
        claseP.add(claseP.size() - 1, "}");
        for (Atributo lista : listas) {
            claseP.add(claseP.size() - 1, "public void update" + lista.getNombre() + "(int id, Object dato)throws SQLException{");
            if (lista.getTipo().equals("String")) {
                claseP.add(claseP.size() - 1, "String sentencia = " + '"' + "update " + lista.getNombre() + " set " + lista.getNombre() + " = " + '"' +"+"+'"'+"'"+'"'+ "+dato+" +'"'+"'"+'"'+"+"+ '"' + "where id = " + '"' + "+id;");
            } else {
                claseP.add(claseP.size() - 1, "String sentencia = " + '"' + "update " + lista.getNombre() + " set " + lista.getNombre() + " = " + '"' + "+dato+" + '"' + "where id = " + '"' + "+id;");
            }
            claseP.add(claseP.size() - 1, "DataBase.getInstance().ejecutarSentencia(sentencia);");
            claseP.add(claseP.size() - 1, "}");
        }
    }

    public void generaDelete(List<String> claseP, String nombreClase, String nombreProyecto, String nomDelete) {
        claseP.add(claseP.size() - 1, "public void delete" + nomDelete + "(int id) throws SQLException{");
        String sentencia = "String sentencia = " + '"' + "delete from " + nombreProyecto + "." + nombreClase + " where id = " + '"' + "+id;";
        claseP.add(claseP.size() - 1, sentencia);
        claseP.add(claseP.size() - 1, "DataBase.getInstance().ejecutarSentencia(sentencia);");
        claseP.add(claseP.size() - 1, "}");
    }

    public void crearDelete(List<Atributo> listas, List<Atributo> atributosNoBasicos, List<String> claseP, String nombreClase, String nombreProyecto) {
        generaDelete(claseP, nombreClase, nombreProyecto, "");
        for (Atributo a : listas) {
            if (esTipoBasico(a.getTipo())) {
                generaDelete(claseP, "lista" + a.getNombre(), nombreProyecto, a.getNombre());
            } else if (a.getTipo().equals("String")) {
                generaDelete(claseP, "lista" + a.getNombre(), nombreProyecto, a.getNombre());
            } else {
                claseP.add(claseP.size() - 1, "public void delete" + a.getNombre() + "(int id) throws SQLException{");
                claseP.add(claseP.size() - 1, "Persistencia" + a.getTipo() + ".getInstance().delete(id);");
                claseP.add(claseP.size() - 1, "}");
            }
        }
        for (Atributo aNB : atributosNoBasicos) {
            claseP.add(claseP.size() - 1, "public void delete" + aNB.getNombre() + "(int id) throws SQLException{");
            claseP.add(claseP.size() - 1, "Persistencia" + aNB.getTipo() + ".getInstance().delete(id);");
            claseP.add(claseP.size() - 1, "}");
        }
    }

    public void crearSelect(List<String> claseP, String nombreClase, String nombreProyecto, List<Atributo> atributos, List<Atributo> listas, List<Atributo> atributosNoBasicos) throws IOException {
        claseP.add(claseP.size() - 1, "public ResulSet selectTodo() throws SQLException{");
        String sentencia = "String sentencia = " + '"' + "select * from " + nombreClase + '"' + ";";
        claseP.add(claseP.size() - 1, sentencia);
        claseP.add(claseP.size() - 1, "return DataBase.getInstance().ejecutarSelecion(sentencia);");
        claseP.add(claseP.size() - 1, "}");

        sentencia = "";

        claseP.add(claseP.size() - 1, "public ResulSet selectFK(String tabla ,String nomFK , int fk) throws SQLException{");
        sentencia = "String sentencia = " + '"' + "select * from " +'"'+ "+tabla+" + '"'+" where "+'"'+"+nomFK+"+'"' +" = "+'"'+"+fk"+ ";";
        claseP.add(claseP.size() - 1, sentencia);
        claseP.add(claseP.size() - 1, "return DataBase.getInstance().ejecutarSelecion(sentencia);");
        claseP.add(claseP.size() - 1, "}");

        sentencia = "";

        claseP.add(claseP.size() - 1, "public ResultSet selectColumna" + "(String columna , Object o) throws SQLException{");
        sentencia = "String sentencia = " + '"' + "select * from " + nombreClase +" where "+'"'+"+columna+"+'"'+" = "+ '"'+"+ id" + ";";
        claseP.add(claseP.size() - 1, sentencia);
        claseP.add(claseP.size() - 1, "return DataBase.getInstance().ejecutarSelecion(sentencia);");
        claseP.add(claseP.size() - 1, "}");

        sentencia="";
        
        claseP.add(claseP.size() - 1, "public " + nombreClase + " select" + "(int id) throws SQLException{");
        sentencia = "String sentencia = " + '"' + "select * from " + nombreClase  + " whrer ID = "+'"'+"+id;";
        claseP.add(claseP.size() - 1, sentencia);
        claseP.add(claseP.size() - 1, "ResultSet rs = DataBase.getInstance().ejecutarSelecion(sentencia);");
        String setAtrubutos = "";

        String claseNew = nombreClase + " clase = new " + nombreClase + "();";
        claseP.add(claseP.size() - 1, claseNew);
        String seleccion = "while (rs.next()){  ";
        claseP.add(claseP.size() - 1, seleccion);
        for (Atributo a : atributos) {
            claseP.add(claseP.size() - 1, "clase.set" + a.getNombre() + "(rs.getObject(" + '"' + a.getNombre() + '"' + "));");
        }
        for (Atributo aNB : atributosNoBasicos) {
            claseP.add(claseP.size() - 1, "clase.set" + aNB.getNombre() + "(Persistencia" + aNB.getTipo() + ".getInstance().selectFK(id,ID_FK" + aNB.getNombre() + "));");
        }
        for (Atributo lista : listas) {
            if (esTipoBasico(lista.getTipo())) {
                crearSelectBasico(claseP, lista);
            } else if (lista.getTipo().equals("String")) {
                crearSelectBasico(claseP, lista);
            } else {
                crearSelectNB(claseP, lista);
            }
        }
        claseP.add(claseP.size() - 1, "}");

    }
    public void crearSelectBasico (List<String> claseP,Atributo lista){
        claseP.add(claseP.size() - 1, "List<"+lista.getTipo()+"> " + lista.getNombre() +" = new ArrayList<"+lista.getTipo()+">();");
        claseP.add(claseP.size() - 1,"ResultSet rs = selectFK("+"list"+lista.getNombre()+","+"ID_FK"+lista.getNombre()+",id);");
        claseP.add(claseP.size() - 1, "while (rs.next()){ "+lista.getNombre()+".add(rs.getObject("+'"'+lista.getNombre()+'"'+"));}");
        claseP.add(claseP.size() - 1,"clase.set"+lista.getNombre()+"("+lista.getNombre()+")");
    }
    public void crearSelectNB(List<String> claseP,Atributo lista){
        claseP.add(claseP.size() - 1, "List<"+lista.getTipo()+"> " + lista.getNombre() +" = new ArrayList<"+lista.getTipo()+">();");
        claseP.add(claseP.size() - 1,"ResultSet rs = selectFK("+'"'+"list"+lista.getNombre()+'"'+","+'"'+"ID_FK"+lista.getNombre()+'"'+",id);");
        claseP.add(claseP.size() - 1, "while (rs.next()){ "+lista.getNombre()+".add(Persistencia"+lista.getTipo()+".getInstance().select(rs.getObject(ID_FK"+lista.getNombre()+"))"+"));}");
        claseP.add(claseP.size() - 1,"clase.set"+lista.getNombre()+"("+lista.getNombre()+")");
    }
//
//
//
//        List<Atributo> modificarSelect = new LinkedList<Atributo>();
//
//        for (Atributo aNB : atributosNoBasicos) {
//            claseP.add(claseP.size() - 1, "clase.set" + aNB.getNombre() + "(Persistencia" + aNB.getTipo() + ".getInstance().select(id," + aNB.getNombre() + "));");
//            modificarSelect.add(aNB);
//        }
//        boolean repetido = false;
//        File file = new File("FIRMASSELECT.txt");
//        List<String> firmas = GuardarArchivo.getInstance().leerTxt(file);
//        for (Atributo modificar : modificarSelect) {
//            for (String txt : firmas) {
//                if (txt.equals(modificar.getTipo())) {
//                    repetido = true;
//                }
//            }
//            if (!repetido) {
//                firmas.add(modificar.getTipo());
//                GuardarArchivo.getInstance().guardarFirmas(firmas, file);
//                // modificarSelect(nombreProyecto, modificar.getTipo(), modificar.getNombre());
//            }
//        }
//        claseP.add(claseP.size() - 1, "return clase;");
//        claseP.add(claseP.size() - 1, "}");
//    }
//
//
//
//
//
//
//
//

//    public void modificarSelect(String nombreProy, String nombreClase, String nombreAtributo) throws IOException {
//        List<String> persistencia = buscarClasePersistencia(nombreProy, nombreClase);
//        int i = buscarProcedimientoIU(persistencia, "select");
//        int contLinea = 0;
//        String aux = "";
//        for (char c : persistencia.get(i).toCharArray()) {
//            if (c != ')') {
//                aux += c;
//            } else {
//                aux += ",int fk,String nomAtributoFK)";
//            }
//        }
//        persistencia.set(i, aux);
//        boolean campos = true;
//        while (campos) {
//            aux = "";
//            i = i + 2;
//            if (persistencia.get(i).equals("}")) {
//                campos = false;
//            } else {
//                for (char ch : persistencia.get(i).toCharArray()) {
//                    if (ch == ';') {
//                        aux += "+" + '"' + " and ID_FK" + nombreAtributo + " = " + '"' + "+id+" + '"' + " and NOMBREATRIBUTOFK = " + '"' + "+nomAtributoFK" + ";";
//                    } else {
//                        aux += ch;
//                    }
//                }
//                persistencia.set(i, aux);
//            }
//        }
//        GuardarArchivo.getInstance().persistirClase(persistencia, "Persistencia" + nombreClase, nombreProy, "class");
//    }
    public void generarPersistencia(String nombreClase, String nombreProy, List<Atributo> listas, List<Atributo> atributosNoBasicos, List<Atributo> atributos) throws IOException {
        List<String> claseP = new ArrayList<String>();
        crearFirma(claseP, nombreClase, nombreProy);
        crearInsert(atributosNoBasicos, listas, atributos, claseP, nombreClase, nombreProy);
        crearUpdate(claseP, atributos, atributosNoBasicos, listas, nombreClase);
        crearDelete(listas, atributosNoBasicos, claseP, nombreClase, nombreProy);
        crearSelect(claseP, nombreClase, nombreProy, atributos, listas, atributosNoBasicos);
        GuardarArchivo.getInstance().persistirClase(claseP, "Persistencia" + nombreClase, nombreProy, "class");
    }
}
